<?php

class SpellWords extends WordsLines
{
    private $_langcode;
    private $_enchantstr;
    
    public function __construct($langcode, &$text)
    {
        $this->_langcode  = $langcode;
        // $this->_text = $text;
        // spell_wordsets is in enchant
        $atmp = spell_wordsets($langcode, $text);
        // $atmp = array();
        // foreach($lines_words as $lw) {
            // if(count($lw) != 2)
                // continue;
            // list($ln, $wd) = $lw;
            // exclude numbers
            // $atmp[] = array($wd, $ln);
        // }
        parent::__construct($atmp);
        // $this->_words_lines = new WordsLines($atmp);
        // presumably array is in location sequence
    }


}

class WordMap
{
    private $_words;
    public function __construct(&$text) {
        $a = array_diff(
                    preg_split(WORD_SPLITTER, lowercase($text),
                    array("")));

    }
}

class WordsLines
{
    private $_words_lines = array(); // array of WordLines objects

    public function __construct($word_line_array)
    {
        // array of "line# word"
        $this->_words_lines = $word_line_array;
    }

    public function WordsAndLines() {
        return $this->_words_lines;
    }

    public function WordsLinesArray() {
        return $this->_words_lines;
    }

    public function WordCount() {
        return count($this->_words_lines);
    }

    public function WordCounts() {
        $a = array();
        foreach($this->_words_lines as $aw => $al) {
            $a[] = array($aw, count($al[1]));
        }
        return $a;
    }

    public function WordItem($word) {
        return isset($this->_words_lines[$word])
            ? $this->_words_lines[$word]
            : null;
    }

    public function WordAndLines($word) {
        $wl = $this->_words_lines[$word];
        return $wl->WordAndLines();
    }
    
    // should this be a static?
    /*
    public function TextSpellWords($langcode, $text) {
        $swl = spell_wordsets($langcode, $text);
        $ary = array();
        foreach($swl as $lw) {
            $a = preg_split("/\s/", $lw);
            if(count($a) != 2)
                continue;
            list($count, $word) = $a;
            if(preg_match("/[\d-]/u", $word))
                continue;
            $ary[] = $a;
        }
        return $ary;
    }
    */
}


class WordLines
{
    private $_lines = array();
    private $_word;

    public function __construct($word, $line) {
        $this->_lines[] = $line;
        $this->_word = $word;
    }

    public function AddLine($line) {
        $this->_lines[] = $line;
    }

    public function Word() {
        return $this->_word;
    }

    public function LineCount() {
        return count($this->_lines);
    }

    public function Lines() {
        sort($this->_lines);
        return $this->_lines;
    }

    public function WordAndCount()
    {
        return "{$this->Word()} ({$this->LineCount()})";
    }

    public function WordAndLines() {
        return array($this->Word(), $this->Lines());
    }
}

// array of pages, each with first line #
// PageNameForLine
// ThreeLines

class PagesLines
{
    private $_aplines = array();
    private $_max = 0;

    public function __construct($project)
    {
        foreach($project->ActivePageRows() as $row) {
            $pgtext = $row['active_text'];
            $this->AddPage($row['pagename'], $row['active_text']);
        }
    }

    public function AddPage($pagename, $text)
    {
        $pl = new PageLines(
                $pagename, $this->_max, $text);   
        $this->_aplines[] = $pl;
        $this->_max += $pl->LineCount();
        // say("$pagename {$this->_max}");
    }

    public function ItemForIndex($index) {
        $imax = $this->PageCount();
        for($i = 0; $i < $imax; $i++) {
            $pgl = $this->_aplines[$i];
            // say("compare {$pgl->LineMin()} and $index");
            if($pgl->LineMin() > $index) {
                break;
            }
        }
        return $this->_aplines[$i];
    }

    public function PageCount() {
        return count($this->_aplines);
    }

    public function Item($index) {
        return $this->_aplines[$index];
    }

    public function PageNameForIndex($index) {
        $pl = $this->ItemForIndex($index);
        return $pl->Name();
    }

    public function PageLineForIndex($index) {
        $pl = $this->ItemForIndex($index);
        return $pl->LineForIndex($index);
    }

    public function PageLineCountForIndex($index) {
        $pl = $this->ItemForIndex($index);
        return $pl->LineCount();
    }

    public function ThreeLinesForIndex($index) {
        $pl = $this->ItemForIndex($index);
        return $pl->LinesFrom($index-2, 3);
    }

    public function PageOfLinesForIndex($index) {
        return $this->ItemForIndex($index);
    }

    public function ItemForOffset($offset) {
        $idx = $this->IndexForOffset($offset);
        return $this->ItemForIndex($idx);
    }
    public function IndexForOffset($offset) {
        $sum = 0;
        $i = 0;
        for($i = 0; $i < $this->PageCount(); $i++) {
            $pg = $this->Item($i);
            $sum += $pg->TextLength();
            if($sum >= $offset) {
                return $i;
            }
            $i++;
        }
        return -1;
    }
}

class PageLines
{
    private $_lines;
    private $_name;
    private $_line_min;
    private $_textlen;

    public function __construct($name, $line_min, $str)
    {
        $this->_line_min = $line_min;
        $this->_name = $name;
        $this->_lines = text_lines($str);
        // $this->_lines = preg_split("/\n/us", $str);
        $this->_textlen = mb_strlen($str);
    }

    public function PageName() {
        return $this->_name;
    }

    public function TextLength() {
        return $this->_textlen;
    }

    public function LineCount() {
        return count($this->_lines);
    }

    public function LineIndexForOffset($offset, $base = 0) {
        $sum = $base;
        if($offset < $base || $offset > $base + $this->_textlen) {
            return -1;
        }
        for($i = 0; $i < $this->LineCount(); $i++) {
            $sum += mb_strlen($this->LineText($i)) + 1;
            if($sum >= $offset) {
                return $i;
            }
        }
        return -1;
    }

    public function LineForIndex($index) {
        return $index - $this->_line_min;
    }

    public function LineMin() {
        return $this->_line_min;
    }

    public function LineMax() {
        return $this->_line_min + count($this->_lines) - 1;
    }

    public function LineText($line) {
        return $this->_lines[$line];
    }

    public function IndexText($index) {
        return $this->LineText(
            $this->LineForIndex($index) - $this->LineMin());
    }

    public function LinesFrom($from, $nlines)
    {
        $l1 = $from - $this->_line_min - 1;
        if($l1 < 0) {
            $l1 = 0;
            $nlines--;
        }
        // say("$from $nlines $l1");
        // dump($this->_lines);
        $ret = implode("", 
                    array_slice($this->_lines, $l1, $nlines));
        // die(h($ret));
        return $ret;
    }

    public function Name() {
        return $this->_name;
    }

    public function Text() {
        return implode("", $this->_lines);
    }
}

?>
